// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package file

import (
	"encoding/json"
	"gitee.com/go-wares/log/base"
	"gitee.com/go-wares/log/conf"
)

type Entity struct {
	Level     base.Level `json:"level"`
	Message   string     `json:"message"`
	Stack     string     `json:"stack,omitempty"`
	Time      string     `json:"time"`
	TimeMicro int64      `json:"time_micro"`

	Pid            int    `json:"pid"`
	ServiceAddr    string `json:"service_addr"`
	ServiceName    string `json:"service_name"`
	ServiceVersion string `json:"service_version"`

	TraceId            string `json:"trace_id"`
	SpanId             string `json:"span_id"`
	SpanPosition       int32  `json:"span_position"`
	ParentSpanId       string `json:"parent_span_id"`
	ParentSpanPosition int32  `json:"parent_span_position"`
}

func (o *Entity) Byte() (body []byte, err error) {
	body, err = json.Marshal(o)
	return
}

func (o *Entity) Init(item *base.Item) *Entity {
	c := conf.Get()

	// Builtin fields.
	o.Pid = c.Pid
	o.ServiceAddr = c.ServiceAddr
	o.ServiceName = c.ServiceName
	o.ServiceVersion = c.ServiceVersion

	// Logger fields.
	o.Level = item.Level
	o.Time = item.Time.Format(c.TimeFormat)
	o.TimeMicro = item.Time.UnixMicro()
	o.Message = item.Text

	// Opentracing
	// append after prefix.
	if item.TraceId != nil {
		o.TraceId = item.TraceId.String()

		if item.ParentSpanId != nil {
			o.ParentSpanId = item.ParentSpanId.String()
			o.ParentSpanPosition = item.ParentSpanPosition
		}

		if item.SpanId != nil {
			o.SpanId = item.SpanId.String()
			o.SpanPosition = item.SpanPosition
		}
	}

	// Backtrace of stack.
	if o.Level.IsFatal() && item.Stack != nil {
		o.Stack = item.Stack.String()
	}
	return o
}
